iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 18
0
自我挑戰組

Metaprogramming Ruby and Rails系列 第 18

Day 18 -- Around Aliases

  • 分享至 

  • xImage
  •  

Around Aliases

在 Ruby 的世界裡,你可以使用 Module#alias_method 幫方法取一個新的別名。從 Ruby 的官方文件可以得知 :

alias_method(new_name, old_name)

Makes new_name a new copy of the method old_name. This can be used to retain access to methods that are overridden.

alias_method() 的第一個參數是『新的方法名稱』,第二個參數是『舊的方法名稱』。參數可用符號(symbol)或是字串(string)表示。

class MyClass
 def my_method; 
   "my_method()" 
  end 
  alias_method :m, :my_method
end

obj = MyClass.new

obj.my_method        # => "my_method()"
obj.m                # => "my_method()"

建立方法的新別名,可以保留原有方法的功能,同時可依需求來改寫方法並命名更適合的新名稱。

class String
  alias_method :real_length, :length
  def length
    real_length > 5 ? "long" : "short"
  end
end

"How are you".length                # => "long"
"How are you".real_length           # => 11

以上面的範例來說:我們重新定義的 String#length(),但是 real_length()仍然可以參照原始的 length() 方法。其實當重新定義方法時,實際上並不是直接改變方法,而是定義了一個新方法,接著把現有的方法名稱連接上去而已。只要ㄧ直有別名連接該方法,舊版本的方法就可以被呼叫。

Around Alias 也是Ruby 黑魔法之一,可以被解析成以下三個步驟:

  1. 幫方法取別名
  2. 重新定義它
  3. 從新方法內呼叫舊方法

其中一個有關於 Around Alias 的缺點就是當方法被重新定義過後,原本的舊方法有可能其他人更改變動,而造成不必要的誤解。因此你可以幫方法取別名後,再將原本的舊方法改為私有方法,就可以避免掉這個問題。

class String
  alias_method :real_length, :length
  def length
    real_length > 5 ? "long" : "short"
  end
  private :real_length
end

"War and Peace".length # => "long"
"War and Peace".send(:real_length) # => "13"
"War and Peace".real_length # => private method… (NoMethodError)

另ㄧ個比較大的問題是 Around Aliases 其實也是ㄧ種形式上的 Monkey patch,這代表著因為方法被重新定義過了,有可能造成與之前撰寫好的程式碼產生衝突。

明天將介紹 另一個 Ruby 的黑魔法 Refinement,將可以解決 Monkey patch 可能產生的問題。


上一篇
Day 17 -- Instance_eval VS Class_eval
下一篇
Day 19 -- Refinement
系列文
Metaprogramming Ruby and Rails33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言